/**
 * 
 */
package cn.nzp.core.openapi.server.si.files;

import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.Iterator;

import javax.annotation.PostConstruct;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;

import cn.hutool.core.date.DateUtil;
import cn.nzp.core.common.consts.CoreConsts;
import cn.nzp.core.common.file.FileTypeConsts;
import cn.nzp.core.common.file.MyFileUtils;
import cn.nzp.core.common.redis.JedisTemplate;
import cn.nzp.core.common.utils.BeanMapper;
import cn.nzp.core.common.utils.CoreUtils;
import cn.nzp.core.openapi.client.dto.files.ApiMediaPropDto;
import cn.nzp.core.openapi.client.dto.files.ApiMediaReqDto;
import cn.nzp.core.openapi.client.files.WxMediaApi;
import cn.nzp.core.query.resp.RespConsts;
import cn.nzp.core.query.resp.ResultResponse;
import cn.nzp.sag.mp.eoa.client.EoaUtilsService;
import cn.nzp.sag.mp.eoa.client.dto.EoaFilePropDto;
import cn.nzp.sag.mp.eoa.client.dto.EoaFileReqDto;
import wb.file.sdk.FileServerClient;
import wb.file.sdk.impl.DefaultFileServerClient;

/**
 * //TODO 企业号套件相关基础接口
 * @author xiejindun
 * 每个Controller遵循命名规范： value用包名，避免冲突
 */
@Path("files/wx")
@Service
@Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
@Produces({ ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8 })
public class WxMediaApiController implements WxMediaApi {

	private final static Logger LOG = LoggerFactory.getLogger(WxMediaApiController.class);
	
	private static final String JPG = "jpg";
	private static final String AMR = "amr";
	
	@Autowired
	private EoaUtilsService eoaUtilsService;
	
	@Value("${file.sdk.baseurl}")
	private String baseurl;
	@Value("${file.sdk.app_code}")
	private String appcode;
	@Value("${file.sdk.password}")
	private String password;

	public static final String EOA_FILE_CHANNEL_EOS = "EOA_FILE_CHANNEL_EOS";
	
	public static final String 	EOA_TIMES_LIMIT = "zs:limit:time:%s:%s";

	@Autowired
	private EoaCosFileHandler eoaCosFileHandler;
	@Autowired
	private JedisTemplate jedisTemplate;
	
	FileServerClient fileClient = null;
    @PostConstruct
    public void init() {
    	if(CoreUtils.isNull(fileClient)) {
    		fileClient = new DefaultFileServerClient();
    	}
    	LOG.info("init-baseUrl:{}, appcode:{}", baseurl, appcode);
    	fileClient.init(baseurl, appcode, password);
    }

	/**
	 * 根据mediaId 获取微信的文件流， 并将文件流上传到我们的文件服务器，生成文件地址
	 */
	@POST
    @Path("get_media_url")
	@Override
	public ResultResponse<ApiMediaPropDto> fetchMediaUrl(ApiMediaReqDto reqDto) {
		ResultResponse<ApiMediaPropDto> resp = new ResultResponse<ApiMediaPropDto>();
		resp.setRescode(RespConsts.PARAM_ERROR);
		try {
			if(CoreUtils.isNull(reqDto) || StringUtils.isBlank(reqDto.getWxcid())
					|| StringUtils.isBlank(reqDto.getMediaid()) || StringUtils.isBlank(reqDto.getBizType())
					|| StringUtils.isBlank(reqDto.getSuffix()) || CoreUtils.isEmpty(reqDto.getOpenId())) {
				resp.setResmsg("参数缺失");
				resp.setRescode(RespConsts.SUCCESS_RET);
				return resp;
			}
			
			String current = DateUtil.format(new Date(), "yyyyMMdd");
			String key = String.format(EOA_TIMES_LIMIT,current, reqDto.getOpenId());
			Integer times = jedisTemplate.getAsInt(key);
			if(CoreUtils.isNull(times)) {
				 jedisTemplate.set(key, "1");
				 times = 0;
			} else {
				 jedisTemplate.incr(key);
			}
			
			if(times > 300) {
				LOG.error("==========error=========openId:{}, time:{}, mobile:{}", reqDto.getOpenId(), times, reqDto.getMobile());
				resp.setRescode(RespConsts.VERIFYFAIL_ERROR);
				resp.setResmsg("error");
				return resp;
			} else {
				LOG.info("============openId:{}, time:{}", reqDto.getOpenId(), times + 1);
			}
			EoaFileReqDto reqMediaIdDto = BeanMapper.map(reqDto, EoaFileReqDto.class);
			//ResultResponse<String> propResp = new ResultResponse<>();
			ResultResponse<String> propResp = eoaUtilsService.getMediaFileWxUrl(reqMediaIdDto);
			
			if(CoreUtils.isNull(propResp)) {
				resp.setRescode(RespConsts.DATA_NOT_EXIST);
				resp.setResmsg("参数错误");
				return resp;
			}
			if(!RespConsts.SUCCESS_RET.equals(propResp.getRescode()) || CoreUtils.isEmpty(propResp.getData())) {
				resp.setRescode(propResp.getRescode());
				resp.setResmsg(propResp.getResmsg());
				return resp;
			}
			
			String fileUrl = this.uploadFile(propResp.getData(), reqDto.getMediaid(), reqDto.getBizType());
			//String fileUrl = this.uploadFile("https://api.weixin.qq.com/cgi-bin/media/get?access_token=48_QWN8weaHD5KsV6GM_z0qLrDejdL9ISaZH_Y6jYIUd5XkpLy-wo-6ULPE_rg8pIu39KJETBGeVpW3dY6vnpmUsstopMMLkmE1d0P2JKDmJLGeiLlluXypyrpZoq9W2cbXkYZO6gy2viudsRVGDOIiAJAZKE&media_id=BQ0wbKjWKdXMbAsaQWp81jfSZMFHE1h70wsShnWquT6WdCiNONCYJz_viMeQQhjj", reqDto.getMediaid(), reqDto.getBizType());
			if(CoreUtils.isEmpty(fileUrl)) {
				resp.setRescode(RespConsts.SYSTEM_BUSY);
				resp.setResmsg("上传文件失败！");
				return resp;
			}
			propResp.setData(fileUrl);
			ApiMediaPropDto mediaPropDto = BeanMapper.map(propResp.getData(), ApiMediaPropDto.class);
			mediaPropDto.setFileUrl(fileUrl);
			
			resp.setData(mediaPropDto);
			resp.setRescode(RespConsts.SUCCESS_RET);
			resp.setResmsg("ok");
		} catch (Exception e) {
			resp.setRescode(RespConsts.SERVICE_ERROR);
			resp.setResmsg("处理异常");
			LOG.error(e.getMessage(), e);
		}
		
		return resp;
	}
	
	/**
	 * 将文件上传到文件服务器
	 * @param url
	 * @param mediaid
	 * @param bizType
	 * @return
	 */
	public String uploadFile(String url, String mediaid, String bizType) {
		EoaFilePropDto filePropDto = new EoaFilePropDto();
		InputStream inputStream = null;  // 文件流
        try{
        	URL fileURL = new URL(url);
        	URLConnection conn = fileURL.openConnection();
            if (conn == null) {
            	// url无法访问
                return null;
            }
            // -1 if the content length is not known, or if the content length is greater than Integer.MAX_VALUE.
            int contentLength = conn.getContentLength();
            String contentType = conn.getContentType();
			filePropDto.setFileSize(contentLength); 
            String fileType = null;  
            inputStream = fileURL.openStream();  
            BufferedInputStream bfis = new BufferedInputStream(inputStream);
            bfis.mark(10); // 先标记（暂存）
            //获取文件头的前六位  
            byte[] b = new byte[3];    
            bfis.read(b, 0, b.length);    
            String fileCode = MyFileUtils.bytesToHexString(b);   
            Iterator<String> keyIter = FileTypeConsts.FILE_TYPE_MAP.keySet().iterator();    
            while(keyIter.hasNext()){    
                String key = keyIter.next();          
                 //比较前几位是否相同就可以判断文件格式（相同格式文件文件头后面几位会有所变化）  
                if(key.toLowerCase().startsWith(fileCode.toLowerCase()) || fileCode.toLowerCase().startsWith(key.toLowerCase())){    
                	fileType = FileTypeConsts.FILE_TYPE_MAP.get(key);    
                    break;    
                }    
            }  
            if(StringUtils.equalsIgnoreCase(contentType, "audio/amr")) {
            	fileType = AMR;
            }
            if(StringUtils.isBlank(fileType)) {
            	LOG.info("UnknowFileType -> content-type:[{}] ,contentLength:[{}], byMediaId:[{}]", contentType, contentLength, mediaid);
            	fileType = JPG;
            }
            filePropDto.setFileType(fileType);
            String fileName = mediaid.concat(CoreConsts.POINT).concat(fileType);
            Long fileSize = 0L;
            if(contentLength > 0) {
            	fileSize = Long.valueOf(contentLength);
            }
            bfis.reset();
            String fileUrl  = "";
            String fileKey = "";
//            String fileKey = eoaCosFileHandler.simpleUploadFileFromStream(bfis, contentType, contentLength);
//			fileUrl = eoaCosFileHandler.getObjectUrl(fileKey);
			String flag = jedisTemplate.get(EOA_FILE_CHANNEL_EOS);
			if (CoreUtils.isNotEmpty(flag) && "Y".equals(flag) && StringUtils.equalsIgnoreCase(bizType, "enroll")) {
				fileKey = eoaCosFileHandler.simpleUploadFileFromStream(bfis, contentType, contentLength, bizType);
				fileUrl = eoaCosFileHandler.getObjectUrl(fileKey);
			} else {
				fileUrl = fileClient.put(bfis, fileName, fileSize, bizType, null, null);
			}
            filePropDto.setFileName(fileName);
            filePropDto.setFileUrl(fileUrl);
            inputStream.close();  
            bfis.close();
            return fileUrl;
        }catch(FileNotFoundException e){
            LOG.error(e.getMessage(), e);
        }catch (IOException e){    
        	LOG.error(e.getMessage(), e);
        }finally {  
            try {  
                inputStream.close();  
            }catch (IOException e) {  
            	LOG.error(e.getMessage(), e);  
            }  
        }      
		return null;
	}
	
	@GET
	@Override
	@Path("/test")
	public String test() {
		LOG.info("=====================================");
		try {
			Thread.currentThread().sleep(15000l);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "hello world";
	}
	
}
